/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#include "TextureCubic.h"
#include "Hardware.h"
#include <Gluck.h>

namespace liba
{
namespace lib3d
{
namespace hard
{
namespace directx8
{

/*D3DTRANSFORMSTATETYPE TextureCubic::transform_mapper[8] =
{
	D3DTS_TEXTURE0, D3DTS_TEXTURE1,
	D3DTS_TEXTURE2, D3DTS_TEXTURE3,
	D3DTS_TEXTURE4, D3DTS_TEXTURE5,
	D3DTS_TEXTURE6, D3DTS_TEXTURE7
};*/

static D3DCUBEMAP_FACES cube_faces[6] = 
{
	D3DCUBEMAP_FACE_POSITIVE_X,
	D3DCUBEMAP_FACE_NEGATIVE_X,    
	D3DCUBEMAP_FACE_POSITIVE_Y,    
	D3DCUBEMAP_FACE_NEGATIVE_Y,    
	D3DCUBEMAP_FACE_POSITIVE_Z,    
	D3DCUBEMAP_FACE_NEGATIVE_Z
};

/*static D3DFORMAT PictureFormatRemapper[]
=
{
	D3DFMT_A8R8G8B8, //32
	D3DFMT_R8G8B8, D3DFMT_A8R8G8B8, // 24
	D3DFMT_R5G6B5, D3DFMT_A1R5G5B5, D3DFMT_A4R4G4B4, D3DFMT_A1R5G5B5 // 16
};*/

TextureCubic::TextureCubic(Hardware * hardware, int mipmap_levels, const pictureformat::Format & desired_format, D3DFORMAT hardware_format, int width, int height)
:	Dependent( hardware ),
	hard::TextureCubic( mipmap_levels, desired_format, width, height ),
	texture( 0 ),
	valid_flag( false )
{
	if( width != height )
		throw Gluck(__FUNCTION__, "Non-square textures are unsupported");
	HRESULT hr = 0;
	if( mipmap_levels != 1 )
		hr = hardware->get_device()->CreateCubeTexture( width, mipmap_levels, 0, hardware_format, D3DPOOL_MANAGED, &texture, 0 );
	if( !texture )
		hr = hardware->get_device()->CreateCubeTexture( width, 1, D3DUSAGE_AUTOGENMIPMAP, hardware_format, D3DPOOL_MANAGED, &texture, 0 );
	if( !texture )
		hr = hardware->get_device()->CreateCubeTexture( width, 1, 0, hardware_format, D3DPOOL_MANAGED, &texture, 0 );
	if( !texture )
		throw Gluck(__FUNCTION__, "create_internal_texture() failed");
	mipmap_levels = this->mipmap_levels = texture->GetLevelCount();
}

TextureCubic::~TextureCubic()
{
	release();
}

void * TextureCubic::lock(int mipmap_level, int plane, int * stride)
{
	IDirect3DSurface9 * cube_face_surface;
	HRESULT hr = texture->GetCubeMapSurface( cube_faces[plane], mipmap_level, &cube_face_surface );
	if( hr != D3D_OK )
		throw Gluck(__FUNCTION__, "texture->GetCubeMapSurface() failed");

	D3DLOCKED_RECT locked_rect;
	if( cube_face_surface->LockRect( &locked_rect, 0, D3DLOCK_NOSYSLOCK ) != D3D_OK )
	{
		cube_face_surface->Release(); cube_face_surface = 0;
		throw Gluck(__FUNCTION__, "cube_face_surface->LockRect() failed");
	}
	cube_face_surface->Release(); cube_face_surface = 0;
	*stride = locked_rect.Pitch;
	return locked_rect.pBits;
}

void TextureCubic::unlock(int mipmap_level, int plane)
{
	IDirect3DSurface9 * cube_face_surface;
	HRESULT hr = texture->GetCubeMapSurface( cube_faces[plane], mipmap_level, &cube_face_surface );
	if( hr != D3D_OK )
		throw Gluck(__FUNCTION__, "texture->GetCubeMapSurface() failed");
	cube_face_surface->UnlockRect();
	cube_face_surface->Release(); cube_face_surface = 0;
//	texture->GenerateMipSubLevels();
	valid_flag = true;
}

bool TextureCubic::is_valid()
{
	return valid_flag;
}

bool TextureCubic::set_in_hardware(int stage)
{
///	if( hardware->test_and_set_last_texture(stage, this) )
///		return true;
	hardware->get_device()->SetTexture( stage, texture );
	return true;
}

void TextureCubic::invalidate()
{
//	valid_flag = false; we are managed :)
}

void TextureCubic::release()
{
	valid_flag = false;

	if( texture )
		int ref_count = texture->Release();
	texture = 0;
}

} // namespace directx8
} // namespace hard
} // namespace lib3d
} // namespace liba


